/* 利用w25q128flash实现物流数据储存  */
#include "w25q_storage.h"

/* 全局变量定义 */
static uint16_t base_year = 0;
static uint8_t base_month = 0;
static uint8_t base_day = 0;
static uint8_t base_hour = 0;
static uint8_t base_minute = 0;
static uint8_t base_second = 0;
static uint32_t base_tick = 0;

static THData samples[MAX_SAMPLES];
static uint8_t current_index = 0;
static bool storage_initialized = false;
#define MAX_TOTAL_DATA_LEN  2048
/* 每月天数表（固定2月为28天，无需闰年判断） */
static const uint8_t days_in_month[] = {
    31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
};
// 在这里定义全局变量（注意：只在一个文件中定义）
char record_env_array[MAX_RECORDS][RECORD_LENGTH] = {0};
char record_gps_array[MAX_RECORDS][RECORD_LENGTH] = {0};

uint16_t valid_record_count = 0;
char total_data_buffer[MAX_TOTAL_DATA_LEN] = {0};
#define MAX_TOTAL_DATA_LEN  2048

/* 外部变量声明 */
extern uint8_t temperature;
extern uint8_t temperature_x;
extern uint8_t humidity;
extern uint8_t sw420_intensity;
extern int lat_int;
extern int lat_dec;
extern int lon_int;
extern int lon_dec;
/* 静态函数声明（内部使用） */
static uint32_t get_sector_addr(int index);
static void get_current_time(uint16_t *year, uint8_t *month, uint8_t *day,
                             uint8_t *hour, uint8_t *minute, uint8_t *second);
static bool is_sector_empty(int index);
static uint32_t count_empty_sectors(uint32_t total_sectors);
static rt_err_t init_storage(void);
static rt_err_t store_current_data(void);
static void read_and_display_all_data(void);
static void storage_thread(void *parameter);


/* 获取扇区地址 */
static uint32_t get_sector_addr(int index) {
    return DATA_STORAGE_ADDR + index * SECTOR_SIZE;
}

/* 获取当前实际时间（简化版，无闰年判断） */
static void get_current_time(uint16_t *year, uint8_t *month, uint8_t *day,
                             uint8_t *hour, uint8_t *minute, uint8_t *second) {
    uint32_t elapsed_seconds = (rt_tick_get() - base_tick) / RT_TICK_PER_SECOND;
    uint16_t y = base_year;
    uint8_t m = base_month;
    uint8_t d = base_day;
    uint8_t h = base_hour;
    uint8_t min = base_minute;
    uint8_t sec = base_second + elapsed_seconds;

    // 秒、分、时进位
    while (sec >= 60) { sec -= 60; min++; }
    while (min >= 60) { min -= 60; h++; }
    while (h >= 24) { h -= 24; d++; }

    // 日期进位（简化，直接按固定每月天数计算）
    while (1) {
        uint8_t days = days_in_month[m - 1];
        if (d > days) {
            d -= days;
            m++;
            if (m > 12) { m = 1; y++; }
        } else {
            break;
        }
    }

    *year = y; *month = m; *day = d;
    *hour = h; *minute = min; *second = sec;
}

/* 时间同步函数 */
void sync_time(int year, int month, int day, int hour, int minute, int second) {
    base_year = year;
    base_month = month;
    base_day = day;
    base_hour = hour;
    base_minute = minute;
    base_second = second;
    base_tick = rt_tick_get();
    LOG_I("Time synced: %04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second);
}

/* 检查扇区是否为空 */
static bool is_sector_empty(int index) {
    THData check_data;
    rt_err_t result = w25q_read_data(get_sector_addr(index), (uint8_t*)&check_data, sizeof(THData));

    // 检查所有字段是否为擦除后的值（uint16_t year为0xFFFF，uint8_t为0xFF）
    return (result == RT_EOK &&
            check_data.year == 0xFFFF &&
            check_data.month == SECTOR_EMPTY &&
            check_data.day == SECTOR_EMPTY &&
            check_data.hour == SECTOR_EMPTY &&
            check_data.minute == SECTOR_EMPTY &&
            check_data.second == SECTOR_EMPTY &&
            check_data.temp_int == SECTOR_EMPTY &&
            check_data.temp_dec == SECTOR_EMPTY &&
            check_data.humi_percent == SECTOR_EMPTY);
}

/* 统计空白扇区数量 */
static uint32_t count_empty_sectors(uint32_t total_sectors) {
    uint32_t empty_count = 0;

    rt_kprintf("\r\n=== Scanning %u sectors for empty spaces ===\r\n", total_sectors);

    for (uint32_t i = 0; i < total_sectors; i++) {
        if (is_sector_empty(i)) {
            empty_count++;
            rt_kprintf("Sector %u: EMPTY\r\n", i);
        } else {
            rt_kprintf("Sector %u: OCCUPIED\r\n", i);
        }

        // 防止刷屏，每100个扇区暂停一下
        if ((i + 1) % 100 == 0) {
            rt_kprintf("Processed %u/%u sectors...\r\n", i + 1, total_sectors);
            rt_thread_mdelay(100);  // 短暂延时
        }
    }

    rt_kprintf("\r\n=== Total %u empty sectors found out of %u ===\r\n", empty_count, total_sectors);
    return empty_count;
}

/* MSH命令：统计空白扇区 */
void cmd_count_empty_sectors(int argc, char *argv[]) {
    uint32_t total_sectors = 4096;  // 默认检查4096个扇区

    // 支持命令行参数指定扇区数量
    if (argc > 1) {
        total_sectors = strtoul(argv[1], NULL, 10);
    }

    count_empty_sectors(total_sectors);
}

/* 初始化存储设备 */
static rt_err_t init_storage(void) {
    storage_initialized = true;
    return RT_EOK;
}

/* 存储当前数据 */
static rt_err_t store_current_data(void) {
    THData data;
    rt_err_t result;
    uint8_t status;
    int target_index = -1;

    // 查找空扇区或循环索引
    for (int i = 0; i < MAX_SAMPLES; i++) {
        if (is_sector_empty(i)) {
            target_index = i;
            break;
        }
    }
    if (target_index == -1) {
        target_index = current_index;
    }
    uint32_t sector_addr = get_sector_addr(target_index);

    // 获取当前实际时间
    uint16_t year;
    uint8_t month, day, hour, minute, second;
    get_current_time(&year, &month, &day, &hour, &minute, &second);

    // 填充数据
    data.year = year;
    data.month = month;
    data.day = day;
    data.hour = hour;
    data.minute = minute;
    data.second = second;
    data.temp_int = temperature;
    data.temp_dec = temperature_x;
    data.humi_percent = humidity;
    data.vibration = sw420_intensity;
    data.lat_int = lat_int;
    data.lat_dec = lat_dec;
    data.lon_int = lon_int;
    data.lon_dec = lon_dec;

    result = w25q_write_enable();
    if (result != RT_EOK) return result;
    result = w25q_erase_sector(sector_addr);
    if (result != RT_EOK) return result;
    do {
        result = w25q_read_status(&status);
        rt_thread_mdelay(10);
    } while (status & 0x01);

    // 写入数据
    result = w25q_write_data(sector_addr, (uint8_t*)&data, sizeof(THData));
    if (result != RT_EOK) {
        w25q_write_enable();
        result = w25q_write_data(sector_addr, (uint8_t*)&data, sizeof(THData));
        if (result != RT_EOK) return result;
    }

    current_index = (target_index + 1) % MAX_SAMPLES;
    return RT_EOK;
}

/* 读取并显示所有温湿度数据（包含所有结构体字段） */
static void read_and_display_all_data(void) {
    THData read_data;
    rt_err_t result;
    uint8_t valid_count = 0;

    LOG_I("\r\n=== Reading all %d records ===\r\n", MAX_SAMPLES);

    for (int i = 0; i < MAX_SAMPLES; i++) {
        uint32_t sector_addr = get_sector_addr(i);
        result = w25q_read_data(sector_addr, (uint8_t*)&read_data, sizeof(THData));

        if (result != RT_EOK) {
            LOG_E("Read sector %d failed", i);
            continue;
        }

        if (is_sector_empty(i)) {
            LOG_I("Record %d: NO DATA (empty sector)", i);
        } else if (read_data.temp_int > 100 || read_data.humi_percent > 100) {
            LOG_I("Record %d: INVALID DATA (out of range)", i);
        } else {
            LOG_I("Record %d: T=%d.%02dC, H=%d%%, %d,geo: %d.%04d,%d.%04d Time=%04d-%02d-%02d %02d:%02d:%02d (sector 0x%08X)",
                  i, read_data.temp_int, read_data.temp_dec,read_data.humi_percent,
                  read_data.vibration,read_data.lon_int, read_data.lon_dec, read_data.lat_int,read_data.lat_dec,
                  read_data.year, read_data.month, read_data.day,
                  read_data.hour, read_data.minute, read_data.second,
                  sector_addr);
            valid_count++;
        }
    }
    LOG_I("\r\n=== Total %d valid records found ===\r\n", valid_count);
}

void read_all_env_data_to_string(void);
void read_all_geo_data_to_string(void);
/* 存储线程（定时采集数据） */
static void storage_thread(void *parameter) {

    rt_thread_mdelay(500);
    LOG_I("data storage started");
    int ci=0;
    if (init_storage() != RT_EOK) {
        LOG_E("Storage initialization failed");
        return;
    }

    while (1) {
        store_current_data();
        rt_thread_mdelay(SAMPLE_INTERVAL);
        ci++;
        if(ci==3)
        {
            ci=0;
            cmd_load_all_data();
        }
    }
}

/* MSH命令：启动存储服务 */
void cmd_start_storage(int argc, char *argv[]) {
    static rt_thread_t tid = RT_NULL;

    if (tid != RT_NULL) {
        LOG_W("Storage service is already running");
        return;
    }

    if (init_storage() != RT_EOK) {
        LOG_E("Storage initialization failed");
        return;
    }

    tid = rt_thread_create("norflash",
                          storage_thread,
                          RT_NULL,
                          2048,
                          25,
                          10);

    if (tid != RT_NULL) {
        rt_thread_startup(tid);
        LOG_I("Storage service started successfully");
    } else {
        LOG_E("Failed to create storage thread");
    }
}

/* MSH命令：查询所有记录 */
void cmd_query_records(int argc, char *argv[]) {
    read_and_display_all_data();
}

/* 固定时间同步函数（使用预定义常量） */
void sync_fixed_time(void) {
    #define FIXED_SYNC_YEAR    2025
    #define FIXED_SYNC_MONTH   7
    #define FIXED_SYNC_DAY     9
    #define FIXED_SYNC_HOUR    23
    #define FIXED_SYNC_MINUTE  15
    #define FIXED_SYNC_SECOND  0

    sync_time(FIXED_SYNC_YEAR, FIXED_SYNC_MONTH, FIXED_SYNC_DAY,
              FIXED_SYNC_HOUR, FIXED_SYNC_MINUTE, FIXED_SYNC_SECOND);

    // 显示同步后的时间
    uint16_t year;
    uint8_t month, day, hour, minute, second;
    get_current_time(&year, &month, &day, &hour, &minute, &second);
    LOG_I("System time fixed to: %04d-%02d-%02d %02d:%02d:%02d",
          year, month, day, hour, minute, second);
}

/* MSH命令：启动固定时间同步 */
void cmd_start_time_sync(int argc, char *argv[]) {
    LOG_I("Starting fixed time synchronization...");
    sync_fixed_time();
    LOG_I("Time synchronization completed!");
}

// 从SPI读取所有有效数据到全局字符串数组
void read_all_env_data_to_string(void) {
    THData read_data;
    valid_record_count = 0;
    memset(record_env_array, 0, sizeof(record_env_array)); // 清空数组

    for (int i = 0; i < MAX_SAMPLES; i++) {
        uint32_t sector_addr = get_sector_addr(i);
        rt_err_t result = w25q_read_data(sector_addr, (uint8_t*)&read_data, sizeof(THData));

        if (result != RT_EOK) {
            LOG_E("Sector %d read failed", i);
            continue;
        }

        // 验证数据有效性（震动强度0-100，温度/湿度合理范围）
        if (read_data.vibration > 100 ||
            read_data.temp_int > 100 ||
            read_data.humi_percent > 100) {
            LOG_W("Sector %d has invalid data (skipped)", i);
            continue;
        }

        // 格式化为：序号 日期时间 温度 湿度 震动强度
        snprintf(record_env_array[valid_record_count], RECORD_LENGTH,
                 "%d %04d/%02d/%02d %02d:%02d:%02d %d.%02d %d %02d",
                 valid_record_count + 1,          // 序号（从1开始）
                 read_data.year, read_data.month, read_data.day,
                 read_data.hour, read_data.minute, read_data.second,
                 read_data.temp_int, read_data.temp_dec,  // 温度（如28.10）
                 read_data.humi_percent,read_data.vibration);             // 震动强度
        valid_record_count++;
        if (valid_record_count >= MAX_RECORDS) break; // 防止数组越界
    }
}


// 从SPI读取所有有效数据到全局字符串数组
void read_all_geo_data_to_string(void) {
    THData read_data;
    valid_record_count = 0;
    memset(record_gps_array, 0, sizeof(record_gps_array)); // 清空数组

    for (int i = 0; i < MAX_SAMPLES; i++) {
        uint32_t sector_addr = get_sector_addr(i);
        rt_err_t result = w25q_read_data(sector_addr, (uint8_t*)&read_data, sizeof(THData));

        if (result != RT_EOK) {
            LOG_E("Sector %d read failed", i);
            continue;
        }

        // 验证数据有效性（震动强度0-100，温度/湿度合理范围）
        if (read_data.vibration > 100 ||
            read_data.temp_int > 100 ||
            read_data.humi_percent > 100) {
            LOG_W("Sector %d has invalid data (skipped)", i);
            continue;
        }

        // 格式化为：序号 日期时间 温度 湿度 震动强度
        snprintf(record_gps_array[valid_record_count], RECORD_LENGTH,
                 "%d %02d/%02d %02d:%02d:%02d %d.%04d %d,%04d",
                 valid_record_count + 1,          // 序号（从1开始）
                 read_data.month, read_data.day,
                 read_data.hour, read_data.minute, read_data.second,
                 read_data.lon_int, read_data.lon_dec,  // 温度（如28.10）
                 read_data.lat_int,read_data.lat_dec);             // 震动强度
        valid_record_count++;
        if (valid_record_count >= MAX_RECORDS) break; // 防止数组越界
    }
}

// MSH命令：读取所有数据
void cmd_load_all_data(int argc, char *argv[]) {
    LOG_I("load valid records...");
    read_all_env_data_to_string();  // 读取数据到字符串数组
    rt_thread_mdelay(200);
    read_all_geo_data_to_string();  // 读取数据到字符串数组
    rt_thread_mdelay(200);
}


// 导出MSH命令

MSH_CMD_EXPORT(cmd_count_empty_sectors, Count empty sectors in storage);
MSH_CMD_EXPORT(cmd_query_records, Query all temperature/humidity records);
MSH_CMD_EXPORT(cmd_start_time_sync, Start fixed time synchronization);
//INIT_APP_EXPORT(cmd_start_storage);
//INIT_APP_EXPORT(sync_fixed_time);
